package com.softwareengineering.trafficapplicationv2;
import java.util.List;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.BaseAdapter;
import android.widget.GridView;
import android.widget.TextView;

/**
 * This file is part of the Traffic Simulation Application.
 * The Traffic Simulation Application is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * The Traffic Simulation Application is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * You should have received a copy of the GNU General Public License
 * along with the Traffic Simulation Application.  If not, see <http://www.gnu.org/licenses/>.
 * 
 * @file ActivityLevels.java
 * @author David Black, Chris Nelson, and Garrett Stibbs, (c) December 03, 2012
 * @description ActivityLevels handles level selection activity
 * @note 	Contains custom LevelAdapter to handle populating
 * 			of GridView containing all playable levels
 * 
 */

public class ActivityLevels extends Activity implements Constants,
		OnClickListener, OnItemClickListener, OnItemLongClickListener {

	//	#########################################
	//		ActivityLevels Member Variables
	//	#########################################
	
	private GridView gridView;	// handle to GridView to populate with selectable levels
	
	//	#####################
	//		LevelAdapter
	//	#####################
	
	// handles population and display of levels in GridView
	public class LevelAdapter extends BaseAdapter {
		// level names to be displayed on buttons
		private String[] levels = {	// corresponds to level codes found in "Constants.java"
				"On\nRamp",	// level code 0
				"Lane\nClosure",	// level code 1
				"Uphill",	// level code 2
				"Four\nWay", //level code 3
				/*"Traffic\nLight" */ };	// level code 4

		// handle to ActivityLevels context
		private Context mContext;

		// list of Score objects to hold high scores for each level
		private List<Score> scores;

		//	#####################
		//		Constructor
		//	#####################
		
		public LevelAdapter(Context context) {
			mContext = context;	// set handle to ActivityLevels context

			DatabaseHandler db = new DatabaseHandler(mContext);	// get DatabaseHandler object to fetch high scores
			scores = db.getHighScores(); // set scores to fetched high scores from local database
			db.close();	// close DatabaseHandler object when finished
		}

		//	#################
		//		Getters
		//	#################
		
		@Override	// returns number of levels
		public int getCount() {
			return levels.length;	// return level count
		}

		@Override	// returns Score for level
		public Object getItem(int position) {
			return scores.get(position);	// return Score object associated with position
		}

		@Override	// returns Id for level
		public long getItemId(int position) {
			return position;	// return position as Id (corresponds to level codes found in "Constants.java"
		}

		@Override	// returns View to display at position
		public View getView(int position, View convertView, ViewGroup parent) {
			TextView title;	// handle to view

			if (convertView == null) {	// if convertView undefined
				title = new TextView(mContext, null, R.style.button);	// create styled TextView
				DisplayMetrics metrics = new DisplayMetrics();	// create metrics Object
				((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getMetrics(metrics);	// get screen metrics
				int size = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 100, metrics);	// convert 100 pix to dp
				title.setLayoutParams(new GridView.LayoutParams(size, size));	// size to 100dp x 100dp
				title.setBackgroundDrawable(mContext.getResources().getDrawable(R.drawable.background_button_level));	// set background
				title.setGravity(Gravity.CENTER);	// center text horizontally and vertically
			} else {	// if convertView defined
				title = (TextView)convertView;	// cast as TextView object
			}

			int score = scores.get(position).getScore();	// get score from associated Score object
			title.setText(levels[position]
					+ (score > 0 ? "\n\u2605 " + score : ""));	// set text to "Level Name\n★ X" where X=high score if applicable

			return title;	// return view
		}

	}
	
	//	#####################################
	//		ActivityLevels Member Methods
	//	#####################################

	// handles launching of appropriate game with Score attachment
	private void doLaunchGame(int scene, Score score) {
		Bundle bundle = new Bundle();	// create new bundle
		bundle.putBoolean("fromLoad", score == null ? false : true);	// specify whether game will be loaded with default (false) or custom (true) configuration
		bundle.putInt("choice_Scen", scene);	// specify appropriate level
		
		if (score != null) {	// if custom configuration
			bundle.putDouble("p_factor", score.getP_factor());	// set politeness factor
			bundle.putDouble("v0_limit", score.getV0_limit());	// set speed limit
		}
		
		Intent intent = new Intent(this, ActivityGame.class);	// create Intent to launch ActivityGame activity
		intent.putExtra("config", bundle);	// put configuration bundle to Intent
		startActivity(intent);	// launch Intent
		finish();	// finish this activity to minimize stack use
	}
	
	//	#####################
	//		Listeners
	//	#####################

	@Override	// handles onClick events
	public void onClick(View view) {
		switch (view.getId()) {	// direct according to View Id
		case R.id.button_highs:	// High Scores launcher button
			startActivity(new Intent(this, ActivityHighs.class));	// launch ActivityHighs activity
			finish();	// finish this activity to minimize stack use
			break;
		}
	}

	@Override	// handles onCreate event
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);	// call super
		setContentView(R.layout.activity_levels);	// set appropriate layout

		gridView = (GridView) findViewById(R.id.gridview);	// get handle to GridView to populate
		gridView.setAdapter(new LevelAdapter(this));	// set adapter to new LevelAdapter (handles population)
		gridView.setOnItemClickListener(this);	// set OnItemClickListener
		gridView.setOnItemLongClickListener(this);	// set OnItemLongClickListener
	}

	@Override	// handles onItemClick events, registered with GridView
	public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
		switch((int)id) {	// direct according to Id corresponding to level codes in "Constants.java"
		case ON_RAMP:	// level code 0
		case LANE_CLOSURE:	// level code 1
		case UPHILL:	// level code 2
		case FOUR_WAY:	// level code 3
		case TRAFFIC_LIGHT: // level code 4
			doLaunchGame((int)id, null);	// launch appropriate game with no Score attachment
			break;
		}
	}

	@Override	// handles onItemLongClick events, registered with GridView
	public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
		switch((int)id) {	// direct according to Id corresponding to level codes in "Constants.java"
		case ON_RAMP:	// level code 0
		case LANE_CLOSURE:	// level code 1
		case UPHILL:	// level code 2
		case FOUR_WAY:	// level code 3
		case TRAFFIC_LIGHT: // level code 4
			Score score = (Score)((LevelAdapter)parent.getAdapter()).getItem(position);	// get Score object associated with position
			if (score != null && score.getScore() > 0) {	// if High Score applicable
				doLaunchGame((int)id, score);	// launch appropriate game with Score attachment
			} else {	// if High Score not applicable
				doLaunchGame((int)id, null);	// launch appropriate game with no Score attachment
			}
			return true;	// absorb event
		}
		
		return false;
	}

	@Override	// handles onKeyDown events
	public boolean onKeyDown(int keyCode, KeyEvent event) {
		switch (keyCode) {	// direct according to keyCode
		case KeyEvent.KEYCODE_BACK:	// Back button
			startActivity(new Intent(this, ActivityLaunch.class)); // launch ActivityLaunch activity
			finish();	// finish this activity to minimize stack use
			return true;	// absorb event
		}
		return super.onKeyDown(keyCode, event);
	}

}
